package cn.lix.sc.rpc.server.impl.controller;

import cn.lix.sc.rpc.impl.common.annotations.RpcService;
import cn.lix.sc.rpc.impl.common.constant.SystemCnt;
import cn.lix.sc.rpc.impl.common.dto.EnhancedRpcRequest;
import cn.lix.sc.rpc.impl.common.dto.EnhancedRpcResponse;
import cn.lix.sc.rpc.impl.common.utils.JsonUtil;
import cn.lix.sc.rpc.server.impl.rpc.EnhancedRpcServerBeanProcessor;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;

/**
 * 增强的RPC控制器，支持多种HTTP请求类型和文件流处理
 *
 * @author lix
 * @date 2024
 */
@RestController
@RequestMapping("/enhancedRpc")
public class EnhancedRpcController {

    private final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(this.getClass());

    @Autowired
    private EnhancedRpcServerBeanProcessor enhancedProcessor;

    /**
     * 增强的RPC调用，支持多种内容类型
     */
    @PostMapping("/enhanced/dispatch")
    public EnhancedRpcResponse enhancedDispatch(@RequestBody EnhancedRpcRequest request, HttpServletRequest httpRequest) {
        String requestId = generateRequestId();
        request.setRequestId(requestId);

        long startTime = System.currentTimeMillis();
        try {
            log.info("增强服务端接口接收到参数：{}", request.toString());

            Object result = enhancedProcessor.invoke(request);
            long cost = System.currentTimeMillis() - startTime;

            // 如果返回结果是文件流，则通过EnhancedRpcResponse返回
            if (result instanceof byte[]) {
                byte[] fileData = (byte[]) result;
                String fileName = request.getOriginalFileName();
                if (fileName == null || fileName.isEmpty()) {
                    fileName = "download_" + System.currentTimeMillis() + ".bin";
                }
                return EnhancedRpcResponse.successFile(fileData, fileName, "application/octet-stream", cost, requestId);
            } else if (result instanceof Resource) {
                // 对于资源响应，读取为字节数组后返回
                try {
                    Resource resource = (Resource) result;
                    // 使用ByteArrayOutputStream读取InputStream（Java 8兼容）
                    java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
                    java.io.InputStream inputStream = resource.getInputStream();
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        baos.write(buffer, 0, bytesRead);
                    }
                    byte[] fileData = baos.toByteArray();
                    String fileName = resource.getFilename();
                    if (fileName == null || fileName.isEmpty()) {
                        fileName = "resource_" + System.currentTimeMillis() + ".bin";
                    }
                    return EnhancedRpcResponse.successFile(fileData, fileName, "application/octet-stream", cost, requestId);
                } catch (IOException e) {
                    log.error("读取资源失败", e);
                    return EnhancedRpcResponse.error("读取资源失败: " + e.getMessage(), cost, requestId);
                }
            }

            // 普通JSON响应
            return EnhancedRpcResponse.success(JsonUtil.obj2String(result), cost, requestId);

        } catch (Throwable e) {
            long cost = System.currentTimeMillis() - startTime;
            log.error("增强RPC调用失败", e);
            return EnhancedRpcResponse.error(e.getMessage(), cost, requestId);
        }
    }

    /**
     * 文件上传RPC调用
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public EnhancedRpcResponse uploadDispatch(
            @RequestParam("serviceClass") String serviceClass,
            @RequestParam("methodKey") String methodKey,
            @RequestParam(value = "beanName", required = false) String beanName,
            @RequestParam(value = "parameters", required = false) String parameters,
            @RequestParam("file") MultipartFile file,
            HttpServletRequest httpRequest) {

        String requestId = generateRequestId();
        long startTime = System.currentTimeMillis();

        try {
            // 构建增强请求对象
            EnhancedRpcRequest request = new EnhancedRpcRequest();
            request.setServiceClass(serviceClass);
            request.setMethodKey(methodKey);
            request.setBeanName(beanName);
            request.setParameters(parameters);
            request.setContentType(RpcService.ContentType.MULTIPART);
            request.setRequestId(requestId);

            // 处理文件数据
            request.setFileData(file.getBytes());
            request.setFileName(file.getName());
            request.setOriginalFileName(file.getOriginalFilename());
            request.setFileSize(file.getSize());
            request.setFileContentType(file.getContentType());

            log.info("文件上传RPC调用：{}, 文件大小：{} bytes", request.toString(), file.getSize());

            Object result = enhancedProcessor.invoke(request);
            long cost = System.currentTimeMillis() - startTime;

            // 处理返回结果
            if (result instanceof byte[]) {
                // 对于文件上传返回文件的情况，暂不支持，返回成功信息
                return EnhancedRpcResponse.success("文件上传成功，但返回结果为文件类型", cost, requestId);
            }

            return EnhancedRpcResponse.success(JsonUtil.obj2String(result), cost, requestId);

        } catch (IOException e) {
            long cost = System.currentTimeMillis() - startTime;
            log.error("文件读取失败", e);
            return EnhancedRpcResponse.error("文件读取失败: " + e.getMessage(), cost, requestId);
        } catch (Throwable e) {
            long cost = System.currentTimeMillis() - startTime;
            log.error("文件上传RPC调用失败", e);
            return EnhancedRpcResponse.error(e.getMessage(), cost, requestId);
        }
    }

    /**
     * 流式数据RPC调用
     */
    @PostMapping(value = "/stream", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public ResponseEntity<?> streamDispatch(
            @RequestParam("serviceClass") String serviceClass,
            @RequestParam("methodKey") String methodKey,
            @RequestParam(value = "beanName", required = false) String beanName,
            @RequestParam(value = "parameters", required = false) String parameters,
            @RequestBody byte[] data,
            HttpServletRequest httpRequest) {

        String requestId = generateRequestId();
        long startTime = System.currentTimeMillis();

        try {
            // 构建增强请求对象
            EnhancedRpcRequest request = new EnhancedRpcRequest();
            request.setServiceClass(serviceClass);
            request.setMethodKey(methodKey);
            request.setBeanName(beanName);
            request.setParameters(parameters);
            request.setContentType(RpcService.ContentType.OCTET_STREAM);
            request.setRequestId(requestId);
            request.setFileData(data);
            request.setFileSize(data.length);

            log.info("流式数据RPC调用：{}, 数据大小：{} bytes", request.toString(), data.length);

            Object result = enhancedProcessor.invoke(request);
            long cost = System.currentTimeMillis() - startTime;

            // 处理返回结果
            if (result instanceof byte[]) {
                return handleFileResponse((byte[]) result, "stream_result.bin", cost, requestId);
            }

            EnhancedRpcResponse response = EnhancedRpcResponse.success(JsonUtil.obj2String(result), cost, requestId);
            return ResponseEntity.ok().body(response);

        } catch (Throwable e) {
            long cost = System.currentTimeMillis() - startTime;
            log.error("流式数据RPC调用失败", e);
            EnhancedRpcResponse errorResponse = EnhancedRpcResponse.error(e.getMessage(), cost, requestId);
            return ResponseEntity.badRequest().body(errorResponse);
        }
    }

    /**
     * 纯文本RPC调用
     */
    @PostMapping(value = "/text", consumes = MediaType.TEXT_PLAIN_VALUE)
    public EnhancedRpcResponse textDispatch(
            @RequestParam("serviceClass") String serviceClass,
            @RequestParam("methodKey") String methodKey,
            @RequestParam(value = "beanName", required = false) String beanName,
            @RequestBody String textData,
            HttpServletRequest httpRequest) {

        String requestId = generateRequestId();
        long startTime = System.currentTimeMillis();

        try {
            // 构建增强请求对象
            EnhancedRpcRequest request = new EnhancedRpcRequest();
            request.setServiceClass(serviceClass);
            request.setMethodKey(methodKey);
            request.setBeanName(beanName);
            request.setParameters(textData);
            request.setContentType(RpcService.ContentType.TEXT_PLAIN);
            request.setRequestId(requestId);

            log.info("文本RPC调用：{}", request.toString());

            Object result = enhancedProcessor.invoke(request);
            long cost = System.currentTimeMillis() - startTime;

            return EnhancedRpcResponse.success(JsonUtil.obj2String(result), cost, requestId);

        } catch (Throwable e) {
            long cost = System.currentTimeMillis() - startTime;
            log.error("文本RPC调用失败", e);
            return EnhancedRpcResponse.error(e.getMessage(), cost, requestId);
        }
    }

    /**
     * 处理文件响应
     */
    private ResponseEntity<Resource> handleFileResponse(byte[] fileData, String fileName, long cost, String requestId) {
        ByteArrayResource resource = new ByteArrayResource(fileData);

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
        headers.add("X-Request-Id", requestId);
        headers.add("X-Cost", String.valueOf(cost));

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    /**
     * 处理资源响应
     */
    private ResponseEntity<Resource> handleResourceResponse(Resource resource, long cost, String requestId) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.add("X-Request-Id", requestId);
        headers.add("X-Cost", String.valueOf(cost));

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(resource.contentLength())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(resource);
    }

    /**
     * 生成请求ID
     */
    private String generateRequestId() {
        return MDC.get(SystemCnt.REQ_ID);
    }
} 